package io.github.uicdb.et;

import com.mojang.logging.LogUtils;
import io.github.uicdb.et.element.BasicElement;
import io.github.uicdb.et.recipe.TurnInRecipeHandlerType;
import io.github.uicdb.et.selection.RandomSelection;
import io.github.uicdb.et.register.RegisterHelper;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.flag.FeatureFlagSet;
import net.minecraft.world.item.*;
import net.minecraft.world.item.alchemy.Potion;
import net.minecraft.world.item.alchemy.PotionContents;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.config.ModConfig;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.fml.loading.FMLEnvironment;
import net.neoforged.neoforge.client.gui.ConfigurationScreen;
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.registries.*;
import org.slf4j.Logger;

// The value here should match an entry in the META-INF/neoforge.mods.toml file
@Mod(ElementalTheory.MODID)
public class ElementalTheory {
    // Define mod id in a common place for everything to reference
    public static final String MODID = "elemental_theory";
    // Directly reference a slf4j logger
    private static final Logger LOGGER = LogUtils.getLogger();

    public static final ResourceKey<Registry<BasicElement>> BASIC_ELEMENT_REGISTRY_RESOURCE_KEY = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(MODID, "element"));

    public static final Registry<BasicElement> BASIC_ELEMENT_REGISTRY = new RegistryBuilder<>(BASIC_ELEMENT_REGISTRY_RESOURCE_KEY)
            .sync(true)
            .create();

    public static final ResourceKey<Registry<TurnInRecipeHandlerType<?>>> TURN_IN_RECIPE_HANDLE_TYPE = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(MODID, "turn_in_recipe_handle_type"));

    public static final Registry<TurnInRecipeHandlerType<?>> TURN_IN_RECIPE_HANDLE_TYPE_REGISTRY = new RegistryBuilder<>(TURN_IN_RECIPE_HANDLE_TYPE)
            .sync(true)
            .create();
    public static final ResourceKey<Registry<RandomSelection>> RANDOM_SELECTION_REGISTRY_RESOURCE_KEY = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(MODID, "random_selection"));

    public static final Registry<RandomSelection> RANDOM_SELECTION_REGISTRY = new RegistryBuilder<>(RANDOM_SELECTION_REGISTRY_RESOURCE_KEY)
            .sync(true)
            .defaultKey(ResourceLocation.fromNamespaceAndPath(MODID, "empty"))
            .create();
    // Create a Deferred Register to hold CreativeModeTabs which will all be registered under the "elemental_theory" namespace
    public static final DeferredRegister<CreativeModeTab> CREATIVE_MODE_TABS = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, MODID);


    // Creates a creative tab with the id "elemental_theory:example_tab" for the example item, that is placed after the combat tab
    public static final DeferredHolder<CreativeModeTab, CreativeModeTab> CREATIVE_MODE_TAB = CREATIVE_MODE_TABS.register("elemental_theory", () -> CreativeModeTab.builder()
            .title(Component.translatable("itemGroup.elemental_theory.core"))
            .withTabsBefore(CreativeModeTabs.COMBAT)
            .icon(Items.DIAMOND.asItem()::getDefaultInstance)
            .build());
    public static final DeferredHolder<CreativeModeTab, CreativeModeTab> CREATIVE_MODE_TAB_TOOL = CREATIVE_MODE_TABS.register("elemental_theory_tool", () -> CreativeModeTab.builder()
            .title(Component.translatable("itemGroup.elemental_theory.tool"))
            .withTabsBefore(CREATIVE_MODE_TAB.getKey())
            .icon(ModItems.WATER_SOURCE_STAFF.asItem()::getDefaultInstance)
            .build());
    public static final DeferredHolder<CreativeModeTab, CreativeModeTab> CREATIVE_MODE_TAB_ARMOR = CREATIVE_MODE_TABS.register("elemental_theory_armor", () -> CreativeModeTab.builder()
            .title(Component.translatable("itemGroup.elemental_theory.armor"))
            .withTabsBefore(CREATIVE_MODE_TAB_TOOL.getKey())
            .icon(Items.NETHERITE_CHESTPLATE::getDefaultInstance)
            .build());
    public static final DeferredHolder<CreativeModeTab, CreativeModeTab> CREATIVE_MODE_TAB_POTION = CREATIVE_MODE_TABS.register("elemental_theory_potion", () -> CreativeModeTab.builder()
            .title(Component.translatable("itemGroup.elemental_theory.consumed"))
            .withTabsBefore(CREATIVE_MODE_TAB_ARMOR.getKey())
            .displayItems((parameters, output) -> {
                generatePotionEffectTypes(output, parameters.holders().lookupOrThrow(BuiltInRegistries.POTION.key()), Items.POTION, parameters.enabledFeatures());
                generatePotionEffectTypes(output, parameters.holders().lookupOrThrow(BuiltInRegistries.POTION.key()), Items.SPLASH_POTION, parameters.enabledFeatures());
                generatePotionEffectTypes(output, parameters.holders().lookupOrThrow(BuiltInRegistries.POTION.key()), Items.LINGERING_POTION, parameters.enabledFeatures());
            })
            .icon(Items.POTION::getDefaultInstance)
            .build());
    public static final DeferredHolder<CreativeModeTab, CreativeModeTab> CREATIVE_MODE_TAB_CURIO = CREATIVE_MODE_TABS.register("elemental_theory_curio", () -> CreativeModeTab.builder()
            .title(Component.translatable("itemGroup.elemental_theory.curio"))
            .withTabsBefore(CREATIVE_MODE_TAB_POTION.getKey())
            .icon(ModItems.RANDOM_CURIO.asItem()::getDefaultInstance)
            .build());

    private static void generatePotionEffectTypes(
            CreativeModeTab.Output output, HolderLookup<Potion> potions, Item item, FeatureFlagSet requiredFeatures
    ) {
        potions.listElements()
                .filter(holder -> holder.value().isEnabled(requiredFeatures))
                .filter(holder -> holder.key().location().getNamespace().equals(MODID))
                .map(holder -> PotionContents.createItemStack(item, holder))
                .forEach(stack -> output.accept(stack, CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS));
    }


    public ElementalTheory(IEventBus modEventBus, ModContainer modContainer) {
        CREATIVE_MODE_TABS.register(modEventBus);
        //伤害类事件处理
        DamageEventHandle.handle(modEventBus, NeoForge.EVENT_BUS);
        GameEventHandle.handle(modEventBus, NeoForge.EVENT_BUS);
        ModEventHandle.handle(modEventBus, NeoForge.EVENT_BUS);
        ClientEventHandle.handle(modEventBus, NeoForge.EVENT_BUS);
        RegisterHelper.init(modEventBus);
        ModRandomSelections.init(modEventBus);
        ModElements.init();
        ModAttributes.init(modEventBus);
        ModEffects.init(modEventBus);
        ModItemDataComponents.init(modEventBus);
        ModAttachments.init(modEventBus);
        ModBlocks.init(modEventBus);
        ModEntityType.init(modEventBus);
        ModBlockEntityType.init(modEventBus);
        ModRecipes.init(modEventBus);
        ModMenuAndScreens.init(modEventBus);
        ModEntityDataSerilizer.init(modEventBus);
        //模组物品注册
        ModItems.init(modEventBus);
        ModTurnInRecipeHandlerTypes.init(modEventBus);
        //增加元素注册表
        modEventBus.addListener(NewRegistryEvent.class, event -> {
            event.register(BASIC_ELEMENT_REGISTRY);
            event.register(RANDOM_SELECTION_REGISTRY);
            event.register(TURN_IN_RECIPE_HANDLE_TYPE_REGISTRY);
        });
        //处理元素注册
        modEventBus.addListener(FMLCommonSetupEvent.class, event -> event.enqueueWork(RegisterHelper::end));
        //注册配置文件
        modContainer.registerConfig(ModConfig.Type.CLIENT, ETConfig.SPEC);

        if (FMLEnvironment.dist == Dist.CLIENT)
            modContainer.registerExtensionPoint(IConfigScreenFactory.class, ConfigurationScreen::new);

    }


}
